//This is NOT going to end well.
//Transfer large string addon, for the wire_clua thing.
//Written by Battle Bott, battlebott@gmail.com
//Documentation:
//http://bottlabs.org/TLS

if (SERVER) then return end

include( "autorun/shared/s_tls.lua" )

//Clientside
if(CLIENT) then
	//tls.downloads[<id>]={
	//	content={<chunk>,<chunk>,...}
	//	recievedchunks=<number of chunks recieved>
	//	totalchunks=<number of chunks to expect>
	//	remaining=<amount remaining>
	//	size=<maximum remaining value>
	//	onfinish=<function to call on finish>
	//}
	function tls.InitDL(um)
		local id=um:ReadLong()
		local totalchunks=um:ReadLong()
		local clientcall=um:ReadString()
		local dl=tls.downloads[id] or {}
		dl.totalchunks=totalchunks
		dl.onfinish=_G[clientcall]
		dl.content={}
		tls.downloads[id]=dl
	end
	usermessage.Hook("tls_initdl",tls.InitDL)
	
	function tls.RecieveDL(um)
		local id=um:ReadLong()
		local chunk=um:ReadString()
		local curchunk=um:ReadLong()
		local remaining=um:ReadLong()
		local dl
		if(tls.downloads[id]==nil) then
			//New download
			dl={}
			dl.content={}
			dl.content[curchunk]=chunk
			dl.curchunk=chunk
			dl.recievedchunks=1
			dl.remaining=remaining
			tls.downloads[id]=dl
		else
			dl=tls.downloads[id]
			dl.content[curchunk]=chunk
			dl.recievedchunks=(dl.recievedchunks or 0)+1
			//In case they arrive out of order:
			dl.remaining=math.min(dl.remaining or tls.settings.maxstringsize+100,remaining)
			dl.size=math.max(dl.size or -1,remaining)
		end
		
		if(dl.recievedchunks==dl.totalchunks) then
			//Finished download
			local download=""
			for key,chunk in ipairs(dl.content) do
				download=download..chunk
			end
			tls.Call(dl.onfinish,download)
			timer.Simple(tls.settings.chunkdelay*3,tls.HaltDL,id)
		end
	end
	usermessage.Hook("tls_senddl",tls.RecieveDL)
	
	function tls.HaltDL(id)
		tls.downloads[id]=nil
	end

	
	//tls.uploads[<id>]={
	//	content=<remaining content>
	//	size=<string size>
	//	remaining=<remaining amount>
	//	curchunk=<current chunk>
	//	onfinish=<on finish function>
	//}
	//Initiate upload, returns the id
	function tls.InitUL(str,servercall,onfinish)
		//If it is bigger exit and call the failure function
		if(string.len(str)>tls.settings.maxstringsize) then
			tls.Call(onfinish,false)
			return
		end
		//Remove newlines.
		str=tls.encode(str)
		file.Write("cl.txt",str)
		local ul={
			content=str,
			size=string.len(str),
			remaining=string.len(str),
			curchunk=1,
			onfinish=onfinish,
		}
		local id=tls.GetID()
		tls.uploads[id]=ul
		LocalPlayer():ConCommand("tls_initul "..tostring(id).." "..
			tostring(math.ceil(ul.size/tls.settings.maxchunksize)).." \""..
			tostring(servercall).."\"")
		tls.SendUL(id)
		return id
	end
	function tls.SendUL(id)
		if(tls.uploads[id]==nil) then
			return
		end
		//ul is just a shortcut, it modifies the original table
		local ul=tls.uploads[id]
		//This nabs the chunk off of the content
		local chunk=ul.content:sub(1,tls.settings.maxchunksize)
		ul.content=ul.content:sub(tls.settings.maxchunksize+1)
		ul.remaining=ul.remaining-tls.settings.maxchunksize
		LocalPlayer():ConCommand("tls_sendul "..tostring(id).." "..
			tostring(ul.curchunk).." "..
			tostring(ul.remaining).." \""..
			tostring(chunk).."\"")
		ul.curchunk=ul.curchunk+1
		if(ul.remaining>0) then
			//Call the next chunk
			timer.Simple(tls.settings.chunkdelay,tls.SendUL,id)
		else
			//Call the onfinish
			timer.Simple(tls.settings.chunkdelay,tls.Call,ul.onfinish,true)
			tls.uploads[id]=nil //Nil out the upload
			tls.ids[id]=nil //Nil out our id
		end
	end
end